\documentclass[b5paper,9pt,twoside,openany]{article}

\input{setting}
\begin{document}
\title{使用gdb+qemu调试Linux}
\author{lenxyang}
\maketitle
\section{工具配置}
首先安装qemu并编译linux内核，而后为Linux提供一个磁盘镜像，创建磁盘镜像使用dd命令即可
\begin{lstlisting}[language=bash]
dd if=/dev/zero of=c.img bs=1024k count=10
mkfs.ext3 c.img
# 安装文件系统
sudo mount -t ext3 -o loop c.img /mnt
# 将busybox生成的文件coyp /mnt下
# 创建配置文件
sudo mkdir /mnt/etc
sudo mkdir /mnt/dev/
sudo mkdir /mnt/etc/rc.d
cat > /tmp/tmp.a
#!/bin/sh
mount -t proc non /proc
mount -t sysfs non /sys
/bin/sh
mv cp /tmp/tmp.a  /mnt/etc/rc.d/rc.sysinit
cat > /tmp/tmp.a
# This is the first script to run when startup
::sysinit:/etc/rc.d/rc.sysinit
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a –r
sudo mv /tmp/tmp.a /mnt/etc/inittab
# 创建字符设备
sudo mkdir /mnt/dev
sudo mknod /mnt/dev/tty0 c 4 0
sudo mknod /mnt/dev/tty1 c 4 1
sudo mknod /mnt/dev/tty2 c 4 2
sudo mknod /mnt/dev/tty3 c 4 3
sudo mknod /mnt/dev/console c 5 1
sudo mknod /mnt/dev/null c 1 1
\end{lstlisting}

\subsection{运行qemu}
\begin{lstlisting}[language=bash]
qemu-system-i386  -hda rootfs.img -m 256 -kernel bzImage -append "root=/dev/hda"
\end{lstlisting}

\section{启动阶段} 

\section{编译内核}
为了能够使gdb尽量无障碍的跟踪Linux，在编译期间必须对Linux的某些编译选项进行更改。
\begin{itemize}
\item 选中Kernel Hacking当中的“Compile the kernel with debug info”
这一点比较容易理解，在编译完成之后会生成一个带有调试信息的vmlinux文件，此文件当中包含对应的符号信息及源代码信息。gdb可以将此文件作为符号文件加载以进行源代码级调试，这对于跟踪代码来说是必不可少的。
\item 在General setup当中去掉 “Optimize for size”并将Makefile当中的“KBUILD\_CFLAGS   += -O2”的-O2改为-O0
带有调试信息之后，用户可以进行源代码级调试。但如果启用O2调试选项，在gdb跟踪代码时，当前代码就会跳来跳去，因为编译器调整了代码的顺序；此外一些变量被优化掉了，没有办法直接查看它的值，这对跟踪代码来说都不方便。通过将O2改为-O能够禁用掉大多数优化策略，已经够用了，根本不用优化将无法通过编译，因此可以也不得不保留一部分优化。
实际上GCC提供了很多优化选项，而-O3, -Os, -O2, -O1和-O0不过是包含了这些具体优化选项的自己，如果希望了解具体的优化选项可以通过man gcc查阅。
\item 选中Kernel Hacking当中的“Compile the kernel with frame pointers”
如果不包含此选项，GCC将使用-fomit-frame-pointer进行编译，gdb将无法打出完整的backtrace信息，给跟踪代码带来不便。

\item 选中Kernel Hacking当中的“Allow gcc to uninline functions marked 'inline'”
\end{itemize}

\subsection{可能出现的错误}
\begin{itemize}
\item 去掉“Device Drivers”->“Character devices”->“ACP Modem (Mwave) support”
在改掉-O2为-O0之后，mware会编译出问题(2.6.32.60)，它是不是必要的去掉它就好。
\item arch/x86/mm/memtest.c:50: undefined reference to `__udivdi3'
\item drivers/serial/serial_core.c:759: undefined reference to `tty_port_users'
\item mm/slab.c:343: undefined reference to `__bad_size'
在 mm/Makefile当中增加一行
\begin{lstlisting}
CFLAGS_slab.o = -O2
\end{lstlisting}
\end{itemize}

\end{document}
